package com.leonzhangxf.springdatastudy.repo.entity;

import com.google.common.collect.Sets;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.annotation.Transient;
import org.springframework.data.domain.AfterDomainEventPublication;
import org.springframework.data.domain.DomainEvents;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Embedded;
import org.springframework.data.relational.core.mapping.MappedCollection;
import org.springframework.data.relational.core.mapping.Table;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.Set;

/**
 * @author leonzhangxf
 */
@Persistent
@Table("student")
@Slf4j
@AllArgsConstructor
@ToString
public class Student {

    @Id
    @Column("id")
    @Getter
    private final Long id;

    @Column("phone")
    @Getter
    @Setter
    private String phone;

    @Column("name")
    @Getter
    @Setter
    private String name;

    @Column("birthday")
    @Getter
    @Setter
    private LocalDateTime birthday;

    @Transient
    @Getter
    @Setter
    private int age;

    @Embedded.Nullable(prefix = "address_")
    @Getter
    @Setter
    private Address address;

    @Embedded.Nullable
    @Getter
    private final AuditData auditData;

    @MappedCollection(idColumn = "student_id")
    @Getter
    @Setter
    private Set<StudentLog> studentLogs;

    @DomainEvents
    StudentSaveOrUpdateEvent submitStudentSaveOrUpdateEvent() {
        log.info("Student save or update");
        return new StudentSaveOrUpdateEvent("student.save");
    }

    @AfterDomainEventPublication
    void studentSaveOrUpdateAfterEvent() {
        log.info("Student save or update after");
    }

    public static Student of(String phone) {
        return new Student(null, phone, null, null, -1,
            null, new AuditData(), Sets.newHashSet());
    }

    @PersistenceConstructor
    Student(Long id, String phone, String name, LocalDateTime birthday, AuditData auditData) {
        this.id = id;
        this.phone = phone;
        this.name = name;
        this.birthday = birthday;
        this.age = Period.between(birthday.toLocalDate(), LocalDate.now()).getYears();
        this.studentLogs = Sets.newHashSet();
        this.auditData = auditData;
    }

    Student withId(Long id) {
        return new Student(id, this.phone, this.name, this.birthday, this.age,
            this.address, this.auditData, this.studentLogs);
    }
}
